package org.dizena.modules.wss.service;

import com.alibaba.fastjson2.JSON;
import org.dizena.base.enums.MessageState;
import org.dizena.base.mq.MqQueue;
import org.dizena.modules.wss.avo.ServerCount;
import org.dizena.modules.wss.bean.Message;
import org.dizena.modules.wss.bean.ServerClient;
import org.dizena.modules.wss.dao.MessageDao;
import org.dizena.modules.wss.dao.ServerClientDao;
import org.dizena.utils.IdGen;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketMessage;
import org.springframework.web.socket.WebSocketSession;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

@Service
public class WsService
{

    @Value("${wss.ip}")
    private String ip;
    @Value("${wss.port}")
    private Integer port;
    @Resource
    private ServerClientDao dao;
    @Resource
    private MessageDao messageDao;
    @Resource
    private MqQueue mq;

    public static Map<String, WebSocketSession> sessionMap = new ConcurrentHashMap<>();

    public void convertAndSend(Message message)
    {
        mq.product(message);
    }

    public void addSocketSession(String clientId, WebSocketSession session)
    {
        if (sessionMap.get(clientId) == null)
        {
            sessionMap.put(clientId, session);
            ServerClient m = new ServerClient();
            m.setClientId(clientId);
            m.setServerId(getServerId());
            dao.save(m);
        }
    }

    public void removeSocketSession(WebSocketSession session)
    {
        Set<Map.Entry<String, WebSocketSession>> sets = sessionMap.entrySet();
        if (sets != null && sets.size() > 0)
        {
            sets.forEach(m ->
            {
                String clientId = m.getKey();
                if (session.getId().equals(m.getValue().getId()))
                {
                    sessionMap.remove(clientId);
                    dao.deleteByClientId(clientId);
                }
            });
        }
    }

    public boolean checkOnline(String fid)
    {
        ServerClient sc = dao.getServerClient(fid);
        if (sc != null)
        {
            return true;
        }
        return false;
    }

    public void sendFeedback(Message message, WebSocketSession session)
    {
        try
        {
            session.sendMessage(new TextMessage(JSON.toJSONString(message)));
        } catch (IOException e)
        {
            e.printStackTrace();
        }
    }

    public void sendHistoryMessage(String clientId, WebSocketSession session)
    {
        List<Message> messages = messageDao.getNotSendToReceiver(clientId);
        if (messages != null && messages.size() > 0)
        {
            messages.forEach(message ->
            {
                try
                {
                    session.sendMessage(new TextMessage(JSON.toJSONString(message)));
                    if (message.getId() != null)
                    {
                        updateMessageStatus(message.getId(), MessageState.ReceiverNotRead);
                    }
                } catch (IOException e)
                {
                    e.printStackTrace();
                }
            });
        }
    }

    public boolean sendMessageToUser(Message message)
    {
        //更新聊天最新时间
        WebSocketSession session = sessionMap.get(message.getReceiver());
        if (session != null)
        {
            if (session.isOpen())
            {
                try
                {
                    session.sendMessage(new TextMessage(JSON.toJSONString(message)));
                    updateMessageStatus(message.getId(), MessageState.ReceiverNotRead);
                    return true;
                } catch (IOException e)
                {
                }
            }
        }
        return false;
    }

    public void updateMessageStatus(String id, MessageState state)
    {
        Message msg = new Message();
        msg.setId(id);
        msg.setImStatus(state.status());
        if (state.equals(MessageState.ReceiverNotRead))
        {
            msg.setArriveTime(System.currentTimeMillis());
        }
        if (state.equals(MessageState.ReceiverHasRead))
        {
            msg.setReadTime(System.currentTimeMillis());
        }
        messageDao.update(msg);
    }

    public String getLinkHost()
    {
        List<ServerCount> counts = dao.countHost();
        List<ServerCount> clients = new ArrayList<>();
        if (counts != null && counts.size() > 1)
        {
            clients.addAll(counts);
            Collections.sort(clients);
            return clients.get(0).getServerId();
        }
        return getServerId();
    }

    public void clearServerClient()
    {
        dao.deleteByServerId(getServerId());
    }

    private String getServerId()
    {
        return ip + ":" + port;
    }

    public Message saveMessage(WebSocketMessage message)
    {
        Message msg = JSON.parseObject(message.getPayload().toString(), Message.class);
        msg.setId(IdGen.get().nextSid());
        msg.setImStatus(MessageState.NotSendToReceiver.status());
        msg.setCreateTime(System.currentTimeMillis());
        return messageDao.add(msg);
    }

    public Message saveMessage(Message msg)
    {
        msg.setId(IdGen.get().nextSid());
        msg.setImStatus(MessageState.NotSendToReceiver.status());
        msg.setCreateTime(System.currentTimeMillis());
        return messageDao.add(msg);
    }

    public List<Message> listChat(String uid, String fid)
    {
        return messageDao.getChat(uid, fid);
    }


}
